﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace UnityNetwork
{
    public class Packet
    {
        //0-1 个字节保存数据长度
        //2-3 个字节保存数据id
        public const int headerLength = 4;          //数据包头
        public short msgid = 0;   //消息id，2字节
        public Socket sk = null;
        public byte[] buffer = new byte[2048];  //保存数据
        public int readLength = 0;   // TCP数据流读取的字节长度
        public short bodyLength = 0;  // 有效数据的长度，2字节
        public bool encoded = false;   //标志是否已经处理过头4个字节

        public Packet(short id,Socket s=null)
        {
            msgid = id;
            sk = s;
            byte[] bs = BitConverter.GetBytes(id);
            bs.CopyTo(buffer, 2);
        }

        public Packet(Packet p)
        {
            msgid = p.msgid;
            sk = p.sk;
            p.buffer.CopyTo(buffer, 0);
            bodyLength = p.bodyLength;
            readLength = p.readLength;
            encoded = p.encoded;
        }

        public void ResetParams()
        {
            msgid = 0;
            readLength = 0;
            bodyLength = 0;
            encoded = false;
        }

        public void EncodeHeader(MemoryStream stream)
        {
            if (stream != null) bodyLength = (short)stream.Position;
            byte[] bs = BitConverter.GetBytes(bodyLength);
            bs.CopyTo(buffer, 0);
            encoded = true;
        }

        public void EncodeBuffer(short netId, byte[] buffer)
        {
            this.bodyLength = (short)(2 + buffer.Length);
            byte[] idBytes = BitConverter.GetBytes(netId);
            byte[] bodyLengthBytes = BitConverter.GetBytes(this.bodyLength);
            bodyLengthBytes.CopyTo(this.buffer, 0);  // 填入消息体加消息id长度
            idBytes.CopyTo(this.buffer, 4);   // 填入消息id
            buffer.CopyTo(this.buffer, 6);    // 填入消息体
            this.encoded = true;
        }

        public void DecodeHeader()
        {
            bodyLength = System.BitConverter.ToInt16(buffer, 0);
            msgid = BitConverter.ToInt16(buffer, 2);
        }

       public MemoryStream Stream
        {
            get
            {
                return new MemoryStream(buffer, headerLength, buffer.Length - headerLength);
            }
        }

        public static byte[] Serialize<T>(T t)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                try
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(stream, t);
                    stream.Seek(0, SeekOrigin.Begin);
                    return stream.ToArray();
                }catch(Exception e)
                {
                    return null;
                }
               
            }
        }

        public static T Deserialize<T>(byte[] bs)
        {
            using (MemoryStream stream = new MemoryStream(bs))
            {
                try
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    T t = (T)bf.Deserialize(stream);
                    return t;
                }
                catch(Exception e)
                {
                    return default(T);
                }
            }
        }
     }
}
